/******************************************************************
 * Copyright 2012 Alpscale Graphics Corporation
 * Copyright (C) 2012 by Alpscale 
 *
 ******************************************************************/

#ifndef __MUSB_HDRC_DEFS_H__
#define __MUSB_HDRC_DEFS_H__

#include "usb.h"
#include "usb_defs.h"


/* Mentor USB core register overlay structure */
#ifndef musb_regs
__packed struct  musb_regs{
	/* common registers */
	uint8_t		faddr;		//0x0
	uint8_t		power;		//0x1
	uint8_t		intrtx1;	//0x2
	uint8_t		intrtx2;	//0x3
	uint8_t		intrrx1;	//0x4
	uint8_t		intrrx2;	//0x5
	uint8_t		intrusb;	//0x6
	uint8_t		intrtxe1;	//0x7
	uint8_t		intrtxe2;	//0x8
	uint8_t		intrrxe1;	//0x9
	uint8_t		intrrxe2;	//0xA
	uint8_t		intrusbe;	//0xB
	uint8_t		frame1;		//0xC
	uint8_t		frame2;		//0xD
	uint8_t		index;		//0xE
	uint8_t		devctl;		//0xF

	/* indexed registers */
	uint8_t		txmaxp;		//0x10
	uint8_t		txcsr1;		//0x11	=CSR0
	uint8_t		txcsr2;		//0x12	=CSR02
	uint8_t		rxmaxp;		//0x13
	uint8_t		rxcsr1;		//0x14
	uint8_t		rxcsr2;		//0x15
	uint8_t		rxcount1;	//0x16
	uint8_t		rxcount2;	//0x17
	
	uint8_t		txtype;			//0x18
	uint8_t		txinterval;		//0x19
	uint8_t		rxtype;			//0x1A
	uint8_t		rxinterval;		//0x1B
	
	uint8_t		txfifo1;			//0x1C
	uint8_t		txfifo2;			//0x1D
	uint8_t		rxfifo1;			//0x1E
	uint8_t		rxfifo2;			//0x1F
	/* fifo */
	uint8_t		fifox[64];		//0x20
} /* __attribute__((packed, aligned(32)))*/;
#endif

/*
 * MUSB Register bits
 */

/* POWER */
#define MUSB_POWER_ISOUPDATE	0x80
#define MUSB_POWER_VBUSVAL	0x40
#define MUSB_POWER_VBUSSESS	0x20
#define MUSB_POWER_VBUSLO	0x10
#define MUSB_POWER_RESET	0x08
#define MUSB_POWER_RESUME	0x04
#define MUSB_POWER_SUSPENDM	0x02
#define MUSB_POWER_ENSUSPEND	0x01
#define MUSB_POWER_HSMODE_SHIFT	4

/* INTRUSB */
#define MUSB_INTR_SUSPEND	0x01
#define MUSB_INTR_RESUME	0x02
#define MUSB_INTR_RESET		0x04
#define MUSB_INTR_BABBLE	0x04
#define MUSB_INTR_SOF		0x08
#define MUSB_INTR_CONNECT	0x10
#define MUSB_INTR_DISCONNECT	0x20
#define MUSB_INTR_SESSREQ	0x40
#define MUSB_INTR_VBUSERROR	0x80	/* For SESSION end */

/* DEVCTL */
#define MUSB_DEVCTL_BDEVICE	0x80
#define MUSB_DEVCTL_FSDEV	0x40
#define MUSB_DEVCTL_LSDEV	0x20
#define MUSB_DEVCTL_PUCON	0x10		//new, no use
#define MUSB_DEVCTL_PDCON	0x08		//new, no use
#define MUSB_DEVCTL_HM		0x04
#define MUSB_DEVCTL_HR		0x02
#define MUSB_DEVCTL_SESSION	0x01

/* CSR0 in Host mode */
#define MUSB_CSR02_FLUSHFIFO	0x01
#define MUSB_CSR0_H_NAKTIMEOUT	0x80
#define MUSB_CSR0_H_STATUSPKT	0x40
#define MUSB_CSR0_H_REQPKT		0x20
#define MUSB_CSR0_H_ERROR		0x10
#define MUSB_CSR0_H_SETUPPKT	0x08
#define MUSB_CSR0_H_RXSTALL		0x04
#define MUSB_CSR0_TXPKTRDY		0x02
#define MUSB_CSR0_RXPKTRDY		0x01

/* CSR0 bits to avoid zeroing (write zero clears, write 1 ignored) */
#define MUSB_CSR0_H_WZC_BITS	(MUSB_CSR0_H_NAKTIMEOUT | MUSB_CSR0_H_RXSTALL | MUSB_CSR0_RXPKTRDY)

/* TxType/RxType */
//#define MUSB_TYPE_SPEED		0xc0
//#define MUSB_TYPE_SPEED_SHIFT	6
//#define MUSB_TYPE_SPEED_HIGH 	1
#define MUSB_TYPE_SPEED_FULL 	2
#define MUSB_TYPE_SPEED_LOW		3

#define MUSB_TYPE_PROTO		0x30	/* Implicitly zero for ep0 */
#define MUSB_TYPE_PROTO_SHIFT	4
#define MUSB_TYPE_REMOTE_END	0xf	/* Implicitly zero for ep0 */
#define MUSB_TYPE_PROTO_BULK 	2
#define MUSB_TYPE_PROTO_INTR 	3

/* TXCSR1 */
#define MUSB_TXCSR2_AUTOSET			0x80
#define MUSB_TXCSR2_ISO				0x40
#define MUSB_TXCSR2_MODE			0x20
#define MUSB_TXCSR2_DMAENAB			0x10
#define MUSB_TXCSR2_FRCDATATOG		0x08
#define MUSB_TXCSR2_DMAMODE			0x04

#define MUSB_TXCSR_H_NAKTIMEOUT		0x80
#define MUSB_TXCSR_CLRDATATOG		0x40
#define MUSB_TXCSR_H_RXSTALL		0x20
#define MUSB_TXCSR_FLUSHFIFO		0x08
#define MUSB_TXCSR_H_ERROR			0x04
#define MUSB_TXCSR_FIFONOTEMPTY		0x02
#define MUSB_TXCSR_TXPKTRDY			0x01

/* TXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */
#define MUSB_TXCSR_H_WZC_BITS	(MUSB_TXCSR_H_NAKTIMEOUT | MUSB_TXCSR_H_RXSTALL | MUSB_TXCSR_H_ERROR | MUSB_TXCSR_FIFONOTEMPTY)

/* RXCSR in Host mode */
#define MUSB_RXCSR2_AUTOCLEAR		0x80
#define MUSB_RXCSR2_H_AUTOREQ		0x40
#define MUSB_RXCSR2_DMAENAB			0x20
#define MUSB_RXCSR2_DMAMODE			0x10

#define MUSB_RXCSR_CLRDATATOG		0x80
#define MUSB_RXCSR_H_RXSTALL		0x40
#define MUSB_RXCSR_H_REQPKT			0x20
#define MUSB_RXCSR_FLUSHFIFO		0x10
#define MUSB_RXCSR_DATAERROR		0x08
#define MUSB_RXCSR_H_ERROR			0x04
#define MUSB_RXCSR_FIFOFULL			0x02
#define MUSB_RXCSR_RXPKTRDY			0x01

/* RXCSR bits to avoid zeroing (write zero clears, write 1 ignored) */
#define MUSB_RXCSR_H_WZC_BITS	(MUSB_RXCSR_H_RXSTALL | MUSB_RXCSR_H_ERROR | MUSB_RXCSR_DATAERROR | MUSB_RXCSR_RXPKTRDY)

/* Endpoint configuration information. Note: The value of endpoint fifo size
 * element should be either 8,16,32,64,128,256,512,1024,2048 or 4096. Other
 * values are not supported
 */
struct musb_epinfo {
	uint8_t	epnum;	/* endpoint number 	*/
	uint8_t	epdir;	/* endpoint direction	*/
	uint16_t	epsize;	/* endpoint FIFO size	*/
};

/*
 * Platform specific MUSB configuration. Any platform using the musb
 * functionality should create one instance of this structure in the
 * platform specific file.
 */
struct musb_config {
	struct	musb_regs	*regs;
	uint32_t			timeout;
	uint8_t			musb_speed;
	uint8_t			extvbus;
};

/* externally defined data */
extern struct musb_config	musb_cfg;
extern struct musb_regs		*musbr;

/* exported functions */
extern void musb_start(void);
extern void musb_configure_ep(const struct musb_epinfo *epinfo, uint8_t cnt);
extern void write_fifo(uint8_t ep, uint32_t length, void *fifo_data);
extern void read_fifo(uint8_t ep, uint32_t length, void *fifo_data);

#if defined(CONFIG_USB_BLACKFIN)
/* Every USB register is accessed as a 16-bit even if the value itself
 * is only 8-bits in size.  Fun stuff.
 */
# undef  readb
# define readb(addr)     (uint8_t)bfin_read16(addr)
# undef  writeb
# define writeb(b, addr) bfin_write16(addr, b)
# undef MUSB_TXCSR_MODE /* not supported */
# define MUSB_TXCSR_MODE 0
/*
 * The USB PHY on current Blackfin processors is a UTMI+ level 2 PHY.
 * However, it has no ULPI support - so there are no registers at all.
 * That means accesses to ULPI_BUSCONTROL have to be abstracted away.
 */
static __inline uint8_t musb_read_ulpi_buscontrol(struct musb_regs *musbr)
{
	return 0;
}
static __inline void musb_write_ulpi_buscontrol(struct musb_regs *musbr, uint8_t val)
{}
#else
static __inline uint8_t musb_read_ulpi_buscontrol(struct musb_regs *musbr)
{
	return 0;
}
static __inline void musb_write_ulpi_buscontrol(struct musb_regs *musbr, uint8_t val)
{
	
}
#endif

#endif	/* __MUSB_HDRC_DEFS_H__ */
